package com.liu.es.test;

import org.apache.http.HttpHost;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;

import java.util.Iterator;

public class ESTest_Doc_Query {
    public static void main(String[] args) throws Exception {

        RestHighLevelClient esClient = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost", 9200, "http"))
        );
        //查询数据
//        SearchRequest request = new SearchRequest();
        //原有的GetRequest不满足我们获取数据的要求，我们需要获取大量数据，需要用到SearchRequest
        //indices方法指定要操作的索引index
//        request.indices("user");
//
        /**
         * SearchSourceBuilder作为查找数据的条件，对数据的条件通过他来添加
         * query来添加一些指定条件，参数是QueryBuilders下的一些指定方法
         */
//        SearchSourceBuilder search = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
//
        /**
         * SearchRequest也类似于IndexRequest的source，都是通过添加内容，不过IndexRequest的source添加的是内容，SearchRequest的source添加
         * 的是查询条件
         */
//        request.source(search);
//
//        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
//        SearchHits hits = response.getHits();
//        System.out.println(hits.getTotalHits());
//        System.out.println(response.getTook());
//        Iterator<SearchHit> iter = hits.iterator();
//        while (iter.hasNext()){
//            System.out.println(iter.next());
//        }

        //条件查询
//
        //分页查询
//        SearchRequest request = new SearchRequest();
//        request.indices("user");
//

//        SearchSourceBuilder search = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
//        //(当前页码-1)*每页显示条数
        /**
         *from指定从哪一页开始，公式：(当前页码-1)*每页显示条数
         * size指定一页有多少条内容
         */
//        search.from(0);
//        search.size(4);
//        request.source(search);
//
//        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
//        SearchHits hits = response.getHits();
//        System.out.println(hits.getTotalHits());
//        System.out.println(response.getTook());
//        Iterator<SearchHit> iter = hits.iterator();
//        while (iter.hasNext()){
//            System.out.println(iter.next());
//        }

        //查询排序
//        SearchRequest request = new SearchRequest();
//        request.indices("user");
//
//        SearchSourceBuilder search = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
//        //排序
        /**                                         字段名               降序 /升序排序
         * sort可以对数据进行排序，接受两个参数：（String fieldName,SortOrder.DESC/ASC）
         */
//        search.sort("age", SortOrder.DESC);
//        request.source(search);
//
//        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
//        SearchHits hits = response.getHits();
//        System.out.println(hits.getTotalHits());
//        System.out.println(response.getTook());
//        Iterator<SearchHit> iter = hits.iterator();
//        while (iter.hasNext()){
//            System.out.println(iter.next());
//        }

//        //过滤字段
//        SearchRequest request = new SearchRequest();
//        request.indices("user");
//
//        SearchSourceBuilder search = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
//        //过滤字段
//        String[] includes = {"name","age"};
//        String[] excludes = {"sex"};
//
        /**
         * fetchSource可以对数据字段进行过滤，接受两个数组参数，一个是要展现哪些字段includes，另一个是不需要展示哪些字段excludes，值得一提的是
         * excludes里出现的字段要是在includes里面也出现过了，实际上这个字段也是不会出现的
         */
//        search.fetchSource(includes,excludes);
//        request.source(search);
//
//        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
//        SearchHits hits = response.getHits();
//        System.out.println(hits.getTotalHits());
//        System.out.println(response.getTook());
//        Iterator<SearchHit> iter = hits.iterator();
//        while (iter.hasNext()){
//            System.out.println(iter.next());
//        }

        //组合查询
//        SearchRequest request = new SearchRequest();
//        request.indices("user");
//
        /**
         * 组合查询通过QueryBuilders.boolQuery()来获取BoolQueryBuilder对象，而我们通过他来添加多重条件
         * boolQueryBuilder有should()、must()、mustNot()这些方法
         *                    或       并        并不
         *matchQuery放入要检索的字段、匹配的数据，这可以放在should或者must、mustNot中
         * 添加完条件之后我们也可以将它放入query中
         */
//        SearchSourceBuilder search = new SearchSourceBuilder();
//        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
////        boolQueryBuilder.must(QueryBuilders.matchQuery("name","xiongda"));
////        boolQueryBuilder.mustNot(QueryBuilders.matchQuery("name","xiongda"));
//        boolQueryBuilder.should(QueryBuilders.matchQuery("age",32));
//        boolQueryBuilder.should(QueryBuilders.matchQuery("age",40));
//        search.query(boolQueryBuilder);
//
//        //过滤字段
//        String[] includes = {"name","age"};
//        String[] excludes = {"sex"};
//
//        search.fetchSource(includes,excludes);
//        request.source(search);
//
//        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
//        SearchHits hits = response.getHits();
//        System.out.println(hits.getTotalHits());
//        System.out.println(response.getTook());
//        Iterator<SearchHit> iter = hits.iterator();
//        while (iter.hasNext()){
//            System.out.println(iter.next());
//        }

        //范围查询
//        SearchRequest request = new SearchRequest();
//        request.indices("user");
//        RangeQueryBuilder age = QueryBuilders.rangeQuery("age");
        /**
         * QueryBuilders.rangeQuery("age")构造函数先去指定对哪个字段进行范围查询，能够获得RangeQueryBuilder这个对象
         * 这个对象有许多方法比如gt、lt、gte、lte来进行范围查询
         *                  大于、小于、大于等于、小于等于
         */
//        age.gte(30);
//        age.lt(70);
//        SearchSourceBuilder search = new SearchSourceBuilder();
//

//        search.query(age);
//        request.source(search);
//
//        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
//        SearchHits hits = response.getHits();
//        System.out.println(hits.getTotalHits());
//        System.out.println(response.getTook());
//        Iterator<SearchHit> iter = hits.iterator();
//        while (iter.hasNext()){
//            System.out.println(iter.next());
//        }

        //模糊查询
//        SearchRequest request = new SearchRequest();
//        request.indices("user");
//
//        SearchSourceBuilder search = new SearchSourceBuilder();
        /**
         * fuzzyQuery用来指定查询那个字段，以及模糊查询的条件，fuzziness是模糊查询后的数据可以有多少位数据相同就展示出来
         */
//        search.query(QueryBuilders.fuzzyQuery("name", "xiong").fuzziness(Fuzziness.TWO));
//        request.source(search);
//
//        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
//        SearchHits hits = response.getHits();
//        System.out.println(hits.getTotalHits());
//        System.out.println(response.getTook());
//        Iterator<SearchHit> iter = hits.iterator();
//        while (iter.hasNext()){
//            System.out.println(iter.next());
//        }

        //高亮查询
//        SearchRequest request = new SearchRequest();
//        request.indices("user");
//
//        SearchSourceBuilder search = new SearchSourceBuilder();
//        TermQueryBuilder termQuery = QueryBuilders.termQuery("name", "zhangsan");
//
//        search.query(termQuery);
//
//        HighlightBuilder highlightBuilder = new HighlightBuilder();
        /**
         * 高亮查询HighlightBuilder可以把指定的字段进行特别标注
         */
//        search.highlighter(highlightBuilder);

//        highlightBuilder.preTags("<font color='red'>");//高亮字段的头标签
//        highlightBuilder.postTags("</font>");//高亮字段的尾标签
//        highlightBuilder.field("name");//要对哪个字段进行高亮查询

//        request.source(search);
//
//        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
//
//        SearchHits hits = response.getHits();
//        System.out.println(hits.getTotalHits());
//        System.out.println(response.getTook());
//        Iterator<SearchHit> iter = hits.iterator();
//        while (iter.hasNext()){
//            System.out.println(iter.next());
//        }

        //聚合查询
        SearchRequest request = new SearchRequest();
        request.indices("user");

        SearchSourceBuilder search = new SearchSourceBuilder();

//        AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age");//最大值
//        TermsAggregationBuilder field = AggregationBuilders.terms("ageGroup").field("age");//分组
        AvgAggregationBuilder field = AggregationBuilders.avg("ageGroup").field("age");//平均数

        search.aggregation(field);


        request.source(search);

        SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

        SearchHits hits = response.getHits();
        System.out.println(hits.getTotalHits());
        System.out.println(response.getTook());
        Iterator<SearchHit> iter = hits.iterator();
        while (iter.hasNext()) {
            System.out.println(iter.next());
        }

        esClient.close();
    }
}
